﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Xml;
using Microsoft.Win32;

namespace SHomeWorkshop.LunarPresentation.Commands
{
    public partial class Command
    {
        /// <summary>
        /// 另存文档。
        /// </summary>
        /// <param name="closeAfterSaveAs">保存后立即关闭文档。</param>
        /// <returns></returns>
        public static bool SaveFileAs()
        {
            if (Globals.selectedEditor == null)
            {
                MessageBox.Show("当前没有文档可以保存！",
                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            Editor editor = Globals.selectedEditor;

            return SaveFileAs(editor);
        }

        /// <summary>
        /// 文档另存为。
        /// </summary>
        /// <param name="editor"></param>
        /// <param name="closeIfHasSamename"></param>
        /// <param name="resultFileName">必须传入合法的文件名（全路径）。</param>
        /// <returns></returns>
        public static bool SaveFileAs(Editor editor, bool closeIfHasSamename = true, string resultFileName = null)
        {
            if (resultFileName == null)
            {
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Title = Globals.appName + "——保存文件：";
                sfd.Filter = Globals.appName +
                    " 文档(*.lpdoc)|*.lpdoc|" + Globals.appName +
                    " 模板文档(*.lptemp)|*.lptemp|Xml文档(*.xml)|*.xml|文本文档(*.txt)|*.txt";
                sfd.FileName = editor.FileNameHeader.Text;

                if (Directory.Exists(Globals.pathofUserDocuments) == false)
                {
                    Directory.CreateDirectory(Globals.pathofUserDocuments);
                }

                sfd.InitialDirectory = Globals.pathofUserDocuments;

                //只有Vista以上版本才支持。
                if (System.Environment.OSVersion.Version.Major >= 6)
                {
                    sfd.CustomPlaces.Add(
                        new FileDialogCustomPlace(Globals.pathofUserDocuments));

                    sfd.CustomPlaces.Add(
                    new FileDialogCustomPlace(Globals.pathOfUserTemplateDocuments));
                }

                string defFileName = "";

                defFileName = GetDefFileNameOfEditor(editor);

                if (defFileName != "")
                {
                    sfd.FileName = defFileName;
                }

                Globals.SwitchInputMethod(true);

                if (sfd.ShowDialog(Globals.MainWindow) != true)
                {
                    editor.ParentWindow.Focus();
                    Globals.SwitchInputMethod(false);
                    return false;
                }

                resultFileName = sfd.FileName;
            }

            // 为防止主窗口快捷键失效，令Editor的ScrollViewer获取焦点。
            editor.ParentWindow.Focus();

            string shortFilename = Editor.GetShortFilenameFromFullname(resultFileName);

            #region 判断是否已打开了一个同名文档。如果有，放弃操作。
            if (OpenedASameNameFile(editor, shortFilename))
            {
                Dialogs.LunarMsgBox.MsgBoxShow(
                    Globals.appName,
                    "已经打开了一个名为【"
                    + shortFilename
                    + "】的文档！",
                    "为防止混淆，如果一定要使用这个文件名，请先关闭【"
                    + shortFilename + "】这个文档，然后再执行本操作。",
                    null,
                    MessageBoxButton.OK,
                    MessageBoxImage.Warning);

                Globals.SwitchInputMethod(false);
                return false;
            }
            #endregion

            if (resultFileName.EndsWith(".lptemp"))
            {
                if (SaveTemplateDocument(editor, resultFileName))
                {
                    editor.FileName = resultFileName;

                    UpdateRecentlyFilesList(resultFileName);

                    return true;
                }
                else return false;
            }
            else
            {
                if (File.Exists(resultFileName))
                {
                    FileAttributes fileAttributes = File.GetAttributes(resultFileName);
                    if (fileAttributes == FileAttributes.ReadOnly)
                    {
                        System.Windows.MessageBox.Show("目标磁盘文档具有“只读”属性，无法写入！",
                            Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                        Globals.SwitchInputMethod(false);
                        return false;
                    }
                }

                // 写到磁盘文档。
                try
                {
                    using (XmlTextWriter xw
                        = new System.Xml.XmlTextWriter(resultFileName, Encoding.UTF8))
                    {
                        xw.Formatting = Formatting.Indented;
                        editor.XmlDocument.WriteTo(xw);
                    }

                    editor.IsModified = false;
                    editor.ModifingsList.PointOfSaving = editor.ModifingsList.Point;

                    UpdateRecentlyFilesList(resultFileName);

                    //保存成功才应改Editor的FileName

                    editor.FileName = resultFileName;

                    return true;
                }
                catch (Exception e)
                {
                    Dialogs.LunarMsgBox.MsgBoxShow(
                        Globals.appName,
                        "保存文件时发生意外错误。",
                        "异常信息如下：\r\n" + e.Message,
                        e.StackTrace, MessageBoxButton.OK, MessageBoxImage.Error);
                    return false;
                }
                finally
                {
                    Globals.SwitchInputMethod(false);
                }
            }
        }

        private static bool SaveTemplateDocument(Editor editor, string fileFullPath)
        {
            if (editor == null || editor.RootPanel == null) return false;

            Expressions.Expression rootPanel = Globals.selectedEditor.RootPanel;

            try
            {
                RenderTargetBitmap rtb;

                //BitmapEncoder encoder = new PngBitmapEncoder();//分辨率只能是96DPI。
                //BitmapEncoder encoder = new GifBitmapEncoder();//分辨率过低。
                //BitmapEncoder encoder = new JpegBitmapEncoder();//分辨率可以是300DPI，但不支持透明底色。
                BitmapEncoder encoder;

                rtb = GetExpressionImage(rootPanel, false);//96DPI
                encoder = new PngBitmapEncoder();

                encoder.Frames.Add(BitmapFrame.Create(rtb));
                using (Stream stm = File.Create(fileFullPath))
                {
                    encoder.Save(stm);
                }

                using (StreamWriter sw = File.AppendText(fileFullPath))
                {
                    sw.WriteLine();
                    sw.WriteLine("<?Lunar Presentation?>");
                    sw.Write(editor.XmlDocument.OuterXml);
                }

                editor.IsModified = false;
                editor.ModifingsList.PointOfSaving = editor.ModifingsList.Point;

                return true;
            }
            catch (Exception ex)
            {
                Dialogs.LunarMsgBox.MsgBoxShow(
                    Globals.appName,
                    "保存模板文档时出现异常。",
                    "信息如下：\r\n" + ex.Message,
                    ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }
            finally
            {
                // 为防止主窗口快捷键失效，令Editor的ScrollViewer获取焦点。
                Globals.MainWindow.Focus();
                Globals.SwitchInputMethod(false);
            }
        }
        
        /// <summary>
        /// 根据能找到的第一个文本块的内容来尝试拟定一个文件短名。
        /// </summary>
        /// <param name="editor"></param>
        /// <returns></returns>
        private static string GetDefFileNameOfEditor(Editor editor)
        {
            string defFileName = "";
            if (editor.RootPanel != null)
            {
                Expressions.BaseText bt = Globals.GetFstBaseText(editor.RootPanel);
                if (bt != null && bt.Text.Length > 0)
                {
                    //Windows系统的文件名中不能包括：\/:*?"<>|
                    if (bt.Text.Contains('\r') == false &&
                        bt.Text.Contains('\n') == false &&
                        bt.Text.Contains('\\') == false &&
                        bt.Text.Contains('/') == false &&
                        bt.Text.Contains(':') == false &&
                        bt.Text.Contains('*') == false &&
                        bt.Text.Contains('?') == false &&
                        bt.Text.Contains('"') == false &&
                        bt.Text.Contains('<') == false &&
                        bt.Text.Contains('>') == false &&
                        bt.Text.Contains('|') == false &&
                        bt.Text.Contains('.') == false)
                    //防止“..主编辑区..”和“..文本块..”啥的被当成文件名。
                    {
                        if (bt.Text.Length <= 24)
                        {
                            defFileName = bt.Text;
                        }
                        else
                        {
                            defFileName = bt.Text.Substring(0, 24);
                            //只取前１０个字符。否则可能过长。
                            //对于ANSI版本的api，文件名长度最大不能超过MAX_PATH ，
                            //其实就是260个字节；
                            //对于Unicode版本，最大长度可以达到32767个宽字符。
                        }
                    }
                }
            }
            return defFileName;
        }

        private static bool OpenedASameNameFile(Editor editor, string shortFilename)
        {
            if (shortFilename == null || shortFilename.Length <= 0) return false;

            if (Globals.selectedEditor == null) return false;

            System.Windows.Controls.TabControl mainTabControl = Globals.selectedEditor.ParentWindow.mainTabControl;

            int editorsCount = mainTabControl.Items.Count;

            for (int i = 0; i < editorsCount; i++)
            {
                Editor e = mainTabControl.Items[i] as Editor;
                if (editor == e) continue;

                if (e.FileNameHeader.Text == shortFilename) return true;
            }

            return false;
        }
    }
}
